package com.ddwl.user.aop;

import cn.hutool.core.util.StrUtil;
import com.ddwl.common.util.HttpUtil;
import com.ddwl.common.util.UUIDGenerator;
import com.ddwl.schema.bo.user.AppLoginBo;
import com.ddwl.schema.vo.user.LoginVo;
import com.ddwl.user.constant.LoginLogTypeEnum;
import com.ddwl.user.constant.LoginTypeEnum;
import com.ddwl.user.dao.model.LoginLog;
import com.ddwl.user.service.LoginLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.util.Map;

/**
 * 登录日志记录处理
 *
 * @author hemiaojun
 */
@Aspect
@Component
@Slf4j
public class LoginLogAspect{
    @Resource
    private LoginLogService loginLogService;

    @Pointcut("execution(* com.ddwl.user.service.LoginService.appLogin(..))")
    public void appLoginPointCut() {
    }
    @Pointcut("execution(* com.ddwl.user.service.LoginService.login(..))")
    public void loginPointCut() {
    }
    @Pointcut("execution(* com.ddwl.user.service.LoginService.logout(..))")
    public void logoutPointCut() {
    }

    @AfterReturning(pointcut = "appLoginPointCut() || loginPointCut()",returning="loginVo")
    public void doAfterLogin(JoinPoint joinPoint,LoginVo loginVo)
    {
        handleLog(joinPoint,loginVo,null);
    }

    @AfterReturning(pointcut = "logoutPointCut()")
    public void doAfterLogout(JoinPoint joinPoint)
    {
        handleLog(joinPoint,null,null);
    }

    @AfterThrowing(pointcut = "appLoginPointCut() || loginPointCut() || logoutPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
        log.error(e.getMessage());
    }

    private void handleLog(JoinPoint joinPoint,LoginVo loginVo, Exception e){
        try{
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            String userAgent = request.getHeader("User-Agent");
            String product = request.getHeader("pk");
            String deviceId=request.getHeader("dk");
            String pt = request.getHeader("pt");
            LoginLog loginLog=new LoginLog();
            Map<String, String> authMap = (Map<String, String>) request.getAttribute("authMap");
            loginLog.setDk(deviceId);
            loginLog.setPk(product);
            loginLog.setPt(pt);
            if(null!=authMap){
                if (StrUtil.isEmpty(loginLog.getPk())) {
                    loginLog.setPk(authMap.get("pk"));
                }
                if(StrUtil.isEmpty(loginLog.getDk())){
                    loginLog.setDk(authMap.get("dk"));
                }
                if(StrUtil.isEmpty(loginLog.getPt())){
                    loginLog.setPt(authMap.get("pt"));
                }
                loginLog.setUserId(authMap.get("uid"));
                loginLog.setNickName(authMap.get("nickname"));
                loginLog.setUserName(authMap.get("userName"));
            }
            loginLog.setId(UUIDGenerator.getShortUUID());
            if(loginVo!=null){
                loginLog.setUserId(loginVo.getId());
                loginLog.setNickName(loginVo.getNickname());
                loginLog.setUserName(loginVo.getUserName());
                loginLog.setType(LoginLogTypeEnum.LOGIN.getValue());
            }else{
                loginLog.setType(LoginLogTypeEnum.LOGOUT.getValue());
            }
            loginLog.setIp(HttpUtil.getIp(request));

            loginLog.setUserAgent(userAgent);

            loginLog.setOperateTime(Instant.now());

            Object[] args = joinPoint.getArgs();

            if (args != null) {
                for (Object arg:args) {
                    if(arg instanceof AppLoginBo){
                        AppLoginBo bo=(AppLoginBo) arg;
                        loginLog.setLoginType(bo.getType());
                        if(LoginTypeEnum.WX.getValue().equals(bo.getType())){
                            loginLog.setAppId(bo.getAppId());
                            loginLog.setDk(bo.getOpenId());
                        }
                    }
                }
            }
            if (LoginLogTypeEnum.LOGIN.getValue().equals(loginLog.getType()) && !loginLogService.isHaveByUserId(loginLog.getUserId())) {
                loginLog.setFirstLogin((byte) 1);
            }
            loginLogService.save(loginLog);
        }catch (Exception ex){
            log.error("处理登录日志时发生异常:{}", ex.getMessage());
        }
    }

}